<script lang="ts">
  import { slide } from 'svelte/transition';
  import { mdiPlus } from '@mdi/js';

  import {
    Button,
    Dialog,
    Drawer,
    Form,
    MultiSelectField,
    MultiSelectOption,
    TextField,
    Toggle,
    ToggleButton,
    ToggleGroup,
    ToggleOption,
    type MenuOption,
  } from 'svelte-ux';
  import Preview from '$lib/components/Preview.svelte';

  let options: MenuOption[] = [
    { label: 'One', value: 1 },
    { label: 'Two', value: 2 },
    { label: 'Three', value: 3 },
    { label: 'Four', value: 4 },
  ];

  const newOption: () => MenuOption = () => {
    return { label: '', value: null };
  };

  const manyOptions = Array.from({ length: 100 }).map((_, i) => ({
    label: `${i + 1}`,
    value: i + 1,
  }));

  let value: number[] | undefined = [3];

  // Filters (Any/Evens/Odds) for demos below
  let msfSelectedStr: 'any' | 'even' | 'odds' = 'any';
  $: msfOptionsFiltered =
    msfSelectedStr === 'even'
      ? options.filter((o) => typeof o.value === 'number' && o.value % 2 === 0)
      : msfSelectedStr === 'odds'
        ? options.filter((o) => typeof o.value === 'number' && o.value % 2 !== 0)
        : options;
</script>

<h1>Examples</h1>

<h2>basic</h2>

<Preview>
  <MultiSelectField {options} {value} on:change={(e) => (value = e.detail.value)} />
</Preview>

<h2>label</h2>

<Preview>
  <MultiSelectField label="Numbers" {options} {value} on:change={(e) => (value = e.detail.value)} />
</Preview>

<h2>options variants</h2>

<Preview>
  <div class="grid gap-3">
    <MultiSelectField
      label="checkbox (default)"
      {options}
      {value}
      optionProps={{ variant: 'checkbox' }}
      on:change={(e) => (value = e.detail.value)}
    />
    <MultiSelectField
      label="checkmark"
      {options}
      {value}
      optionProps={{ variant: 'checkmark' }}
      on:change={(e) => (value = e.detail.value)}
    />
    <MultiSelectField
      label="fill"
      {options}
      {value}
      optionProps={{ variant: 'fill' }}
      on:change={(e) => (value = e.detail.value)}
    />
  </div>
</Preview>

<h2>disabled</h2>

<Preview>
  <MultiSelectField {options} {value} on:change={(e) => (value = e.detail.value)} disabled />
</Preview>

<h2>maintainOrder</h2>

<Preview>
  <MultiSelectField {options} {value} on:change={(e) => (value = e.detail.value)} maintainOrder />
</Preview>

<h2>max selected</h2>

<Preview>
  <MultiSelectField {options} {value} max={2} on:change={(e) => (value = e.detail.value)} />
</Preview>

<h2>max selected with warning</h2>

<Preview>
  <MultiSelectField {options} {value} max={2} on:change={(e) => (value = e.detail.value)}>
    <svelte:fragment slot="beforeOptions" let:selection>
      {#if selection.isMaxSelected()}
        <div
          class="bg-danger/5 border-danger text-danger-600 border text-sm font-semibold p-2 rounded mb-1"
          transition:slide
        >
          Maximum selection reached
        </div>
      {/if}
    </svelte:fragment>
  </MultiSelectField>
</Preview>

<h2>many options</h2>

<Preview>
  <MultiSelectField
    options={manyOptions}
    {value}
    on:change={(e) => (value = e.detail.value)}
    classes={{
      multiSelectMenu: {
        menu: 'max-h-[360px]',
      },
    }}
    menuProps={{ autoPlacement: true }}
  />
</Preview>

<h2>Immediately apply changes (no actions) w/ maintainOrder</h2>

<Preview>
  <MultiSelectField
    {options}
    {value}
    on:change={(e) => (value = e.detail.value)}
    mode="immediate"
    maintainOrder
  />
</Preview>

<h2>Immediately apply changes (with custom action) w/ maintainOrder</h2>

<Preview>
  <MultiSelectField
    {options}
    {value}
    on:change={(e) => (value = e.detail.value)}
    mode="immediate"
    maintainOrder
  >
    <div slot="actions">
      <Button color="primary" icon={mdiPlus}>Add item</Button>
    </div>
  </MultiSelectField>
</Preview>

<h2>formatSelected</h2>

<Preview>
  <MultiSelectField
    {options}
    {value}
    formatSelected={({ options }) => options.map((o) => o.label).join(', ') || 'None'}
    on:change={(e) => (value = e.detail.value)}
  />
</Preview>

<h2>beforeOptions slot</h2>

<Preview>
  <MultiSelectField
    options={msfOptionsFiltered}
    {value}
    on:change={(e) => (value = e.detail.value)}
  >
    <svelte:fragment slot="beforeOptions">
      <div class="p-2 border-b">
        <ToggleGroup
          bind:value={msfSelectedStr}
          classes={{ options: 'justify-start h-10' }}
          rounded="full"
          inset
        >
          <ToggleOption value="any">Any</ToggleOption>
          <ToggleOption value="even">Evens</ToggleOption>
          <ToggleOption value="odds">Odds</ToggleOption>
        </ToggleGroup>
      </div>
    </svelte:fragment>
  </MultiSelectField>
</Preview>

<h2>afterOptions slot</h2>

<Preview>
  <MultiSelectField
    options={msfOptionsFiltered}
    {value}
    on:change={(e) => (value = e.detail.value)}
  >
    <svelte:fragment slot="afterOptions">
      <div class="p-2 border-t">
        <ToggleGroup
          bind:value={msfSelectedStr}
          classes={{ options: 'justify-start h-10' }}
          rounded="full"
          inset
        >
          <ToggleOption value="any">Any</ToggleOption>
          <ToggleOption value="even">Evens</ToggleOption>
          <ToggleOption value="odds">Odds</ToggleOption>
        </ToggleGroup>
      </div>
    </svelte:fragment>
  </MultiSelectField>
</Preview>

<h2>actions slot</h2>

<Preview>
  <MultiSelectField {options} {value} on:change={(e) => (value = e.detail.value)}>
    <div slot="actions" class="p-2" on:click|stopPropagation role="none">
      <Toggle let:on={open} let:toggle>
        <Button icon={mdiPlus} color="primary" on:click={toggle}>New item</Button>
        <Form
          initial={newOption()}
          on:change={(e) => {
            // Convert value to number if it's a valid number, otherwise keep as string
            const newOptionData = { ...e.detail };
            if (
              newOptionData.value !== null &&
              newOptionData.value !== '' &&
              !isNaN(Number(newOptionData.value))
            ) {
              newOptionData.value = Number(newOptionData.value);
            }
            options = [newOptionData, ...options];
            // Auto-select the newly created option
            value = [...(value || []), newOptionData.value];
          }}
          let:draft
          let:current
          let:commit
          let:revert
        >
          <Dialog
            {open}
            on:close={() => {
              toggle();
            }}
          >
            <div slot="title">Create new option</div>
            <div class="px-6 py-3 w-96 grid gap-2">
              <TextField
                label="Label"
                value={current.label}
                on:change={(e) => {
                  draft.label = e.detail.value;
                }}
                autofocus
              />
              <TextField
                label="Value"
                value={draft.value}
                on:change={(e) => {
                  draft.value = e.detail.value;
                }}
              />
            </div>
            <div slot="actions">
              <Button
                on:click={() => {
                  commit();
                  toggle();
                }}
                color="primary">Add option</Button
              >
              <Button
                on:click={() => {
                  revert();
                  toggle();
                }}>Cancel</Button
              >
            </div>
          </Dialog>
        </Form>
      </Toggle>
    </div>
  </MultiSelectField>
</Preview>

<h2>actions slot with max warning</h2>

<Preview>
  <MultiSelectField {options} {value} on:change={(e) => (value = e.detail.value)} max={2}>
    <div slot="actions" let:selection class="flex items-center">
      {#if selection.isMaxSelected()}
        <div class="text-sm text-danger">Maximum selection reached</div>
      {/if}
    </div>
  </MultiSelectField>
</Preview>
<h2>within Drawer</h2>

<Preview>
  <ToggleButton let:on={open}>
    Open Drawer
    <Drawer slot="toggle" let:toggleOff {open} on:close={toggleOff} class="w-[400px]">
      <div class="p-4">
        <MultiSelectField {options} {value} on:change={(e) => (value = e.detail.value)} />
      </div>
      <div slot="actions">
        <Button on:click={toggleOff}>Close</Button>
      </div>
    </Drawer>
  </ToggleButton>
</Preview>

<h2>option slot</h2>

<Preview>
  <MultiSelectField {options} {value} on:change={(e) => (value = e.detail.value)}>
    <MultiSelectOption
      slot="option"
      let:option
      let:label
      let:value
      let:checked
      let:indeterminate
      let:onChange
      {checked}
      {indeterminate}
      on:change={onChange}
    >
      <span class="uppercase text-danger">{label}</span>
    </MultiSelectOption>
  </MultiSelectField>
</Preview>
